
import os
import tempfile
from typing import List, Dict
import pdfplumber
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.parsers import MultiPartParser, FormParser
from openai import OpenAI

# 导入混合检索函数
from rag.job_recommendation.job_recommendation import hybrid_search_jobs


@method_decorator(csrf_exempt, name='dispatch')
class BossJobRecommendationView(APIView):
    """
    岗位推荐API视图
    接收PDF简历，执行混合检索，调用大模型生成推荐理由
    """
    parser_classes = (MultiPartParser, FormParser)
    authentication_classes = []  # 禁用认证
    permission_classes = []  # 禁用权限检查

    def post(self, request):
        """
        处理岗位推荐请求
        
        请求参数:
        - file: PDF简历文件
        - top_k: 返回岗位数量，默认8
        - weight_es: ES权重，默认0.6
        - weight_chroma: ChromaDB权重，默认0.4
        
        返回:
        - jobs: 推荐岗位列表
        - resume_summary: 简历摘要
        - total_count: 总推荐数量
        """
        try:
            # 1. 获取请求参数
            file_obj = request.FILES.get("file")
            if not file_obj:
                return Response(
                    {"error": "缺少PDF文件参数"}, 
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            top_k = int(request.data.get("top_k", 8))
            weight_es = float(request.data.get("weight_es", 0.6))
            weight_chroma = float(request.data.get("weight_chroma", 0.4))
            
            # 2. 保存临时文件并提取文本
            resume_text = self._extract_pdf_text(file_obj)
            if not resume_text:
                return Response(
                    {"error": "无法从PDF提取文本，请检查文件格式"}, 
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            # 3. 执行混合检索
            print(f"开始混合检索，查询文本长度: {len(resume_text)}")
            job_results = hybrid_search_jobs(
                query_text=resume_text,
                top_k=top_k,
                weight_es=weight_es,
                weight_chroma=weight_chroma
            )
            
            if not job_results:
                return Response(
                    {"error": "未找到匹配的岗位，请尝试调整搜索条件"}, 
                    status=status.HTTP_404_NOT_FOUND
                )
            
            # 4. 生成推荐理由
            print("开始生成推荐理由...")
            recommendations = self._generate_recommendations(job_results, resume_text)
            
            # 5. 构建响应数据
            response_data = {
                "jobs": recommendations,
                "resume_summary": self._extract_resume_summary(resume_text),
                "total_count": len(recommendations),
                "search_params": {
                    "top_k": top_k,
                    "weight_es": weight_es,
                    "weight_chroma": weight_chroma
                }
            }
            
            print(f"推荐完成，返回{len(recommendations)}个岗位")
            return Response(response_data, status=status.HTTP_200_OK)
            
        except Exception as e:
            print(f"岗位推荐出错: {str(e)}")
            return Response(
                {"error": f"服务器内部错误: {str(e)}"}, 
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )

    def _extract_pdf_text(self, file_obj) -> str:
        """
        从PDF文件中提取文本
        
        Args:
            file_obj: 上传的文件对象
            
        Returns:
            str: 提取的文本内容
        """
        try:
            # 保存临时文件
            with tempfile.NamedTemporaryFile(delete=False, suffix=".pdf") as tmp:
                for chunk in file_obj.chunks():
                    tmp.write(chunk)
                tmp_path = tmp.name
            
            # 提取文本
            texts = []
            with pdfplumber.open(tmp_path) as pdf:
                for page in pdf.pages:
                    page_text = page.extract_text()
                    if page_text:
                        texts.append(page_text.strip())
            
            # 清理临时文件
            try:
                os.remove(tmp_path)
            except Exception:
                pass
            
            return "\n".join(texts).strip()
            
        except Exception as e:
            print(f"PDF文本提取失败: {str(e)}")
            return ""

    def _generate_recommendations(self, job_results: List[Dict], resume_text: str) -> List[Dict]:
        """
        为每个岗位生成推荐理由
        
        Args:
            job_results: 检索到的岗位列表
            resume_text: 简历文本
            
        Returns:
            List[Dict]: 包含推荐理由的岗位列表
        """
        try:
            # 初始化OpenAI客户端
            api_key = os.getenv("DASHSCOPE_API_KEY")
            if not api_key:
                raise ValueError("请设置DASHSCOPE_API_KEY环境变量")
            
            client = OpenAI(
                api_key=api_key,
                base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
            )
            
            recommendations = []
            resume_summary = resume_text[:1500]  # 截断避免过长
            
            for job in job_results:
                try:
                    # 构建推荐理由的提示词
                    recommendation_reason = self._generate_single_recommendation(
                        client, job, resume_summary
                    )
                    
                    # 构建推荐结果
                    recommendation = {
                        "id": job.get("id"),
                        "title": job.get("title", ""),
                        "company": job.get("company", ""),
                        "city": job.get("city", ""),
                        "tags": job.get("tags", ""),
                        "education": job.get("education", ""),
                        "job_str": job.get("job_str", ""),
                        "reason": recommendation_reason,
                        "scores": {
                            "fused_score": job.get("_fused_score", 0.0),
                            "es_score": job.get("_es_original_score", 0.0),
                            "chroma_score": job.get("_chroma_original_score", 0.0)
                        }
                    }
                    recommendations.append(recommendation)
                    
                except Exception as e:
                    print(f"生成岗位{job.get('id')}推荐理由失败: {str(e)}")
                    # 使用默认理由
                    recommendation = {
                        "id": job.get("id"),
                        "title": job.get("title", ""),
                        "company": job.get("company", ""),
                        "city": job.get("city", ""),
                        "tags": job.get("tags", ""),
                        "education": job.get("education", ""),
                        "job_str": job.get("job_str", ""),
                        "reason": "该岗位与您的背景匹配度较高，建议关注",
                        "scores": {
                            "fused_score": job.get("_fused_score", 0.0),
                            "es_score": job.get("_es_original_score", 0.0),
                            "chroma_score": job.get("_chroma_original_score", 0.0)
                        }
                    }
                    recommendations.append(recommendation)
            
            return recommendations
            
        except Exception as e:
            print(f"生成推荐理由失败: {str(e)}")
            # 返回不带理由的基础推荐
            return [
                {
                    "id": job.get("id"),
                    "title": job.get("title", ""),
                    "company": job.get("company", ""),
                    "city": job.get("city", ""),
                    "tags": job.get("tags", ""),
                    "education": job.get("education", ""),
                    "job_str": job.get("job_str", ""),
                    "reason": "该岗位与您的背景匹配度较高",
                    "scores": {
                        "fused_score": job.get("_fused_score", 0.0),
                        "es_score": job.get("_es_original_score", 0.0),
                        "chroma_score": job.get("_chroma_original_score", 0.0)
                    }
                }
                for job in job_results
            ]

    def _generate_single_recommendation(self, client: OpenAI, job: Dict, resume_summary: str) -> str:
        """
        为单个岗位生成推荐理由
        
        Args:
            client: OpenAI客户端
            job: 岗位信息
            resume_summary: 简历摘要
            
        Returns:
            str: 推荐理由
        """
        title = job.get("title", "")
        company = job.get("company", "")
        city = job.get("city", "")
        tags = job.get("tags", "")
        job_str = job.get("job_str", "")[:800]  # 截断岗位描述
        
        # 构建系统提示词
        system_prompt = """你是专业的职业顾问。基于简历内容和岗位信息，为求职者生成个性化的岗位推荐理由。

要求：
1. 分析简历与岗位的匹配点
2. 突出岗位的优势和特点
3. 给出具体的推荐理由
4. 语言简洁专业，每条理由20-30字
5. 避免模板化，要针对性强"""

        # 构建用户提示词
        user_prompt = f"""简历摘要：
{resume_summary}

目标岗位：
职位：{title}
公司：{company}
城市：{city}
标签：{tags}
岗位描述：{job_str}

请基于以上信息，生成3-4条针对这个具体岗位的推荐理由："""

        # 调用大模型
        response = client.chat.completions.create(
            model="qwen-plus",
            messages=[
                {"role": "system", "content": system_prompt},
                {"role": "user", "content": user_prompt}
            ],
            temperature=0.3,
            max_tokens=300
        )
        
        return response.choices[0].message.content.strip()

    def _extract_resume_summary(self, resume_text: str) -> str:
        """
        提取简历摘要
        
        Args:
            resume_text: 完整简历文本
            
        Returns:
            str: 简历摘要
        """
        # 简单的摘要提取：取前500字符
        summary = resume_text[:500]
        if len(resume_text) > 500:
            summary += "..."
        return summary